﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using System.Reflection;
using System.ComponentModel;
using System.Collections;

namespace Petaframe.DataAccess
{

    /// <summary>
    /// Expression tree kullanarak reflection dan kaynaklanan performans kaybı önlenmek istendi fakat olmadı. örnek olarak duruyor.
    /// </summary>
    internal static class ClassDecomposer2
    {


        //public static Expression<Func<T, IParameterBuilder, IEscapeSqlIdentifier, TableInfo>> CreateTableInfoFromEntity<T>()
        //{
            

        //    //parameters
        //    ParameterExpression parameterBuilder = Expression.Parameter(typeof(IParameterBuilder), "parameterBuilder");
        //    ParameterExpression entity = Expression.Parameter(typeof(T), "entity");
        //    ParameterExpression escapeSql = Expression.Parameter(typeof(IEscapeSqlIdentifier), "escapeSql");


        //    //outerblock variables
        //    ParameterExpression tableinfo = Expression.Variable(typeof(TableInfo), "tableinfo");
        //    ParameterExpression tableNameAttribute=Expression.Variable(typeof(TableNameAttribute),"tableNameAttribute");
        //    ParameterExpression index = Expression.Variable(typeof(int), "index");
        //    ParameterExpression propertyInfoArray = Expression.Variable(typeof(PropertyInfo[]), "propertyInfoArray");
        //    ParameterExpression entityType = Expression.Variable(typeof(Type), "entity_Type");


        //    //innerblock variables
        //    ParameterExpression enumerator = Expression.Variable(typeof(IEnumerator), "enumerator");
        //    ParameterExpression currentelement = Expression.Variable(typeof(PropertyInfo), "currentelement");
        //    ParameterExpression customPropertyInfo = Expression.Variable(typeof(CustomPropertyInfo), "customPropertyInfo");
        //    ParameterExpression parameterInfo = Expression.Variable(typeof(ParameterInfo), "parameterInfo");
        //    ParameterExpression propertAttributes = Expression.Variable(typeof(object[]), "propertAttributes");
        //    MethodCallExpression movenext = Expression.Call(enumerator, typeof(IEnumerator).GetMethod("MoveNext"));
        //    LabelTarget looplabel = Expression.Label("looplabel");


        //    BlockExpression innerBlock = Expression.Block(new ParameterExpression[] { enumerator, currentelement, customPropertyInfo, parameterInfo, propertAttributes },
        //         Expression.Assign(enumerator, Expression.Call(propertyInfoArray, typeof(IEnumerable).GetMethod("GetEnumerator"))),
        //         Expression.Loop(
        //            Expression.IfThenElse(Expression.NotEqual(movenext, Expression.Constant(false)),
        //                Expression.Block(
        //                    Expression.Assign(currentelement, Expression.TypeAs(Expression.Property(enumerator, "Current"), typeof(PropertyInfo))),
        //                    Expression.Assign(customPropertyInfo, Expression.New(typeof(CustomPropertyInfo))),
        //                    Expression.Assign(Expression.Property(customPropertyInfo, "CurrentPropertyDetails"), currentelement),
        //                    Expression.Assign(Expression.Property(customPropertyInfo, "PropertyName"), Expression.Property(currentelement, "Name")),
        //                    Expression.Assign(Expression.Property(customPropertyInfo, "PropertyType"), Expression.Property(currentelement, "PropertyType")),
        //                    Expression.Assign(parameterInfo, Expression.Call(parameterBuilder, "CreateParameter", null, index, currentelement)),
        //                     Expression.Assign(propertAttributes, Expression.Call(currentelement, "GetCustomAttributes", null, Expression.Constant(typeof(TablePrimaryKeyAttribute)), Expression.Constant(false))),
        //                     Expression.IfThen(Expression.GreaterThan(Expression.Property(propertAttributes, "Length"), Expression.Constant(0)),
        //                        Expression.Block(
        //                            Expression.Assign(Expression.Property(tableinfo, "HasPrimaryKey"), Expression.Constant(true)),
        //                            Expression.Assign(Expression.Property(customPropertyInfo, "PrimaryKey"), Expression.Constant(true)),
        //                            Expression.Assign(Expression.Property(customPropertyInfo, "AutoIncrement"), Expression.Property(Expression.TypeAs(Expression.ArrayIndex(propertAttributes, Expression.Constant(0)), typeof(TablePrimaryKeyAttribute)), "AutoIncrement")),
        //                            Expression.Call(Expression.Property(tableinfo, "PrimaryKeys"), "Add", null, Expression.Property(currentelement, "Name"))
        //                                       )),
        //                     Expression.Call(Expression.Property(tableinfo, "Properties"), "Add", null, customPropertyInfo),
        //                     Expression.Call(Expression.Property(tableinfo, "Parameters"), "Add", null, Expression.Property(currentelement, "Name"), parameterInfo),
        //                     Expression.PostIncrementAssign(index)
        //                                    ), Expression.Break(looplabel)

        //                                ),
        //                            looplabel)
        //        );


        //    BlockExpression outerblock = Expression.Block(new ParameterExpression[] { tableinfo, tableNameAttribute, entityType, index, propertyInfoArray },
        //         Expression.Assign(tableinfo, Expression.New(typeof(TableInfo))),
        //         Expression.Assign(tableNameAttribute, Expression.TypeAs(Expression.Call(typeof(Attribute), "GetCustomAttribute", null, Expression.Constant(typeof(T)), Expression.Constant(typeof(TableNameAttribute)), Expression.Constant(false)), typeof(TableNameAttribute))),
        //         Expression.Assign(Expression.Property(tableinfo, "TableName"), Expression.Call(escapeSql, "EscapeSqlIdentifier", null, Expression.Property(tableNameAttribute, "TableName"))),
        //         Expression.Assign(entityType, Expression.Call(entity, "GetType", null, null)),
        //         Expression.Assign(propertyInfoArray, Expression.Call(entityType, "GetProperties", null, Expression.Constant(BindingFlags.Instance | BindingFlags.Public))),
        //         Expression.Assign(index, Expression.Constant(0)),
        //         innerBlock,
        //        tableinfo
        //         );


        //    return Expression.Lambda<Func<T, IParameterBuilder, IEscapeSqlIdentifier, TableInfo>>(outerblock, entity, parameterBuilder, escapeSql);
          
            
        //}

        //public static Func<Type, IParameterBuilder, IEscapeSqlIdentifier, TableInfo> CreateTableInfoFromType()
        //{
        //    //parameters
        //    ParameterExpression parameterBuilder = Expression.Parameter(typeof(IParameterBuilder), "parameterBuilder");
        //    ParameterExpression entity = Expression.Parameter(typeof(Type), "entity");
        //    ParameterExpression escapeSql = Expression.Parameter(typeof(IEscapeSqlIdentifier), "escapeSql");


        //    //outerblock variables
        //    ParameterExpression tableinfo = Expression.Variable(typeof(TableInfo), "tableinfo");
        //    ParameterExpression tableNameAttribute = Expression.Variable(typeof(TableNameAttribute), "tableNameAttribute");
        //    ParameterExpression index = Expression.Variable(typeof(int), "index");
        //    ParameterExpression propertyInfoArray = Expression.Variable(typeof(PropertyInfo[]), "propertyInfoArray");
        //   // ParameterExpression entityType = Expression.Variable(typeof(Type), "entity_Type");


        //    //innerblock variables
        //    ParameterExpression enumerator = Expression.Variable(typeof(IEnumerator), "enumerator");
        //    ParameterExpression currentelement = Expression.Variable(typeof(PropertyInfo), "currentelement");
        //    ParameterExpression customPropertyInfo = Expression.Variable(typeof(CustomPropertyInfo), "customPropertyInfo");
        //    ParameterExpression parameterInfo = Expression.Variable(typeof(ParameterInfo), "parameterInfo");
        //    ParameterExpression propertAttributes = Expression.Variable(typeof(object[]), "propertAttributes");
        //    MethodCallExpression movenext = Expression.Call(enumerator, typeof(IEnumerator).GetMethod("MoveNext"));
        //    LabelTarget looplabel = Expression.Label("looplabel");


        //    BlockExpression innerBlock = Expression.Block(new ParameterExpression[] { enumerator, currentelement, customPropertyInfo, parameterInfo, propertAttributes },
        //         Expression.Assign(enumerator, Expression.Call(propertyInfoArray, typeof(IEnumerable).GetMethod("GetEnumerator"))),
        //         Expression.Loop(
        //            Expression.IfThenElse(Expression.NotEqual(movenext, Expression.Constant(false)),
        //                Expression.Block(
        //                    Expression.Assign(currentelement, Expression.TypeAs(Expression.Property(enumerator, "Current"), typeof(PropertyInfo))),
        //                    Expression.Assign(customPropertyInfo, Expression.New(typeof(CustomPropertyInfo))),
        //                    Expression.Assign(Expression.Property(customPropertyInfo, "CurrentPropertyDetails"), currentelement),
        //                    Expression.Assign(Expression.Property(customPropertyInfo, "PropertyName"), Expression.Property(currentelement, "Name")),
        //                    Expression.Assign(Expression.Property(customPropertyInfo, "PropertyType"), Expression.Property(currentelement, "PropertyType")),
        //                    Expression.Assign(parameterInfo, Expression.Call(parameterBuilder, "CreateParameter", null, index, currentelement)),
        //                     Expression.Assign(propertAttributes, Expression.Call(currentelement, "GetCustomAttributes", null, Expression.Constant(typeof(TablePrimaryKeyAttribute)), Expression.Constant(false))),
        //                     Expression.IfThen(Expression.GreaterThan(Expression.Property(propertAttributes, "Length"), Expression.Constant(0)),
        //                        Expression.Block(
        //                            Expression.Assign(Expression.Property(tableinfo, "HasPrimaryKey"), Expression.Constant(true)),
        //                            Expression.Assign(Expression.Property(customPropertyInfo, "PrimaryKey"), Expression.Constant(true)),
        //                            Expression.Assign(Expression.Property(customPropertyInfo, "AutoIncrement"), Expression.Property(Expression.TypeAs(Expression.ArrayIndex(propertAttributes, Expression.Constant(0)), typeof(TablePrimaryKeyAttribute)), "AutoIncrement")),
        //                            Expression.Call(Expression.Property(tableinfo, "PrimaryKeys"), "Add", null, Expression.Property(currentelement, "Name"))
        //                                       )),
        //                     Expression.Call(Expression.Property(tableinfo, "Properties"), "Add", null, customPropertyInfo),
        //                     Expression.Call(Expression.Property(tableinfo, "Parameters"), "Add", null, Expression.Property(currentelement, "Name"), parameterInfo),
        //                     Expression.PostIncrementAssign(index)
        //                                    ), Expression.Break(looplabel)

        //                                ),
        //                            looplabel)
        //        );

            
        //    BlockExpression outerblock = Expression.Block(new ParameterExpression[] { tableinfo, tableNameAttribute,  index, propertyInfoArray },
        //         Expression.Assign(tableinfo, Expression.New(typeof(TableInfo))),
        //         Expression.Assign(tableNameAttribute, Expression.TypeAs(Expression.Call(typeof(Attribute), "GetCustomAttribute", null, entity, Expression.Constant(typeof(TableNameAttribute)), Expression.Constant(false)), typeof(TableNameAttribute))),
        //         Expression.Assign(Expression.Property(tableinfo, "TableName"), Expression.Call(escapeSql, "EscapeSqlIdentifier", null, Expression.Property(tableNameAttribute, "TableName"))),
                
        //         Expression.Assign(propertyInfoArray, Expression.Call(entity, "GetProperties", null, Expression.Constant(BindingFlags.Instance | BindingFlags.Public))),
        //         Expression.Assign(index, Expression.Constant(0)),
        //         innerBlock,
        //        tableinfo
        //         );


        //    return Expression.Lambda<Func<Type, IParameterBuilder, IEscapeSqlIdentifier, TableInfo>>(outerblock, entity, parameterBuilder, escapeSql).Compile();
        //}
       
    }
}
